package dao

import (
	"github.com/astaxie/beego/orm"
	"github.com/pkg/errors"
	"github.com/spf13/cast"
	"nft-server/model"
)

type AssetDao struct {
	BaseDao
}

type IAssetDao interface {
	SaveAsset(asset *model.Asset) error
	GetAsset(assetId string) (*model.Asset, error)
	GetAssets(num int) ([]*model.Asset, error)
	UpdateAsset(asset *model.Asset) error
	DeleteAssets(assetId string) error
	GetAssetsByUserId(userId int, page, pageSize int) ([]*model.Asset, int, error)
	GetAssetByAssetId(AssetId string) (*model.Asset, error)
	InsertMultiAsset(asset []*model.Asset) (int64, error)
}

func GetAssetDao() IAssetDao {
	dao := &AssetDao{}
	dao.Init()
	return dao
}
func (ad *AssetDao) InsertMultiAsset(asset []*model.Asset) (int64, error) {
	nums, err := ad.O.InsertMulti(len(asset), asset)
	return nums, err
}
func (ad *AssetDao) SaveAsset(asset *model.Asset) error {
	_, err := ad.O.Insert(asset)
	if err != nil {
		return errors.Errorf("insert error: %v", err)
	}
	return err
}
func (ad *AssetDao) UpdateAsset(asset *model.Asset) error {
	_, err := ad.O.Update(asset)
	if err != nil {
		return errors.Errorf("Update error: %v", err)
	}
	return err
}

//此处的id是collectionIndex和tokenId拼接而成
func (ad *AssetDao) GetAsset(assetId string) (*model.Asset, error) {
	asset := new(model.Asset)
	asset.IdWithCollectionIndex = assetId
	err := ad.O.Read(asset)
	if err != nil {
		if err == orm.ErrNoRows {
			return nil, nil
		}
		return nil, errors.Errorf("read error: %v", err)
	}
	return asset, nil
}

func (ad *AssetDao) GetAssets(num int) ([]*model.Asset, error) {
	var assets []*model.Asset
	_, err := ad.O.QueryTable(&model.Asset{}).OrderBy("-CreatedTime").Limit(num).All(&assets)
	if err != nil {
		return nil, errors.Errorf("query table error: %v", err)
	}
	return assets, nil
}

func (ad *AssetDao) GetAssetsByUserId(userId int, page, pageSize int) ([]*model.Asset, int, error) {
	var assets []*model.Asset

	offset := page - 1
	if page-1 < 0 {
		offset = 0
	}
	offset = offset * pageSize

	recode := ad.O.QueryTable(&model.Asset{}).Filter("owner", userId)
	totalNum, err := recode.Count()
	recode.Offset(offset).Limit(pageSize).RelatedSel().All(&assets)
	if err != nil {
		return nil, 0, errors.Errorf("query table error: %v", err)
	}
	return assets, cast.ToInt(totalNum), nil
}

func (ad *AssetDao) DeleteAssets(assetId string) error {
	asset := new(model.Asset)
	asset.IdWithCollectionIndex = assetId
	_, err := ad.O.Delete(asset, "idWithCollectionIndex")
	if err != nil {
		return errors.Errorf("delete asset error: %v", err)
	}
	return nil
}

func (ad *AssetDao) GetAssetByAssetId(AssetId string) (*model.Asset, error) {
	asset := new(model.Asset)
	err := ad.O.QueryTable(new(model.Asset)).Filter("assetId", AssetId).RelatedSel().One(asset)
	if err != nil {
		if err == orm.ErrNoRows {
			return nil, nil
		}
		return nil, errors.Errorf("read error: %v", err)
	}
	return asset, nil
}
